#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "cmsis_os2.h"
#include "ohos_init.h"
#include "wifi_device.h"
#include "wifi_hotspot.h"
#include "wifi_error_code.h"
#include "lwip/netifapi.h"
#include "cJSON.h"

#include "iot_gpio.h"

// 变化参数
#define HMDTU_AP_SSID "HMNetDTU-12345678"
#define HMDTU_AP_PSK  "66668888"
#define HMDTU_AP_UDP_PORT 8888

#define WifiAP_Restart "restart"
#define WifiAP_GetData "getData"
#define WifiAP_Hello "hello"

#define HMDTU_TIP_LED 9
#define HMDTU_ONE_SECOND 1
#define HMDTU_DEF_TIMEOUT 15

static void OnHotspotStaJoinHandler(StationInfo *info);
static void OnHotspotStateChangedHandler(int state);
static void OnHotspotStaLeaveHandler(StationInfo *info);

static struct netif *g_lwip_netif = NULL;
static int g_apEnableSuccess = 0;
WifiEvent g_wifiEventHandler = {0};
WifiErrorCode error;
static char HBKDTU_udp_recvBuf[2000] = {0};
static char HBKDTU_udp_send_ok[20] = "GET_DATA_OK";
static char HBKDTU_udp_send_error[20] = "GET_DATA_ERROR";
static char HBKDTU_udp_send_hello[20] = "HBKIOT_HELLO";

osEventFlagsId_t WIFIAP_flagID;
uint32_t WIFIAP_flags;
char * WIFIAP_wifiData;
int WIFIAP_sock_fd;
int ** WIFIAP_wifiDataLength;
struct sockaddr_in WIFIAP_client_addr;


void Wifi_AP_led(int time){
    IoTGpioSetOutputVal(HMDTU_TIP_LED, 0);
    osDelay(time);
    IoTGpioSetOutputVal(HMDTU_TIP_LED, 1);
    osDelay(time);
    IoTGpioSetOutputVal(HMDTU_TIP_LED, 0);
    osDelay(time);
    IoTGpioSetOutputVal(HMDTU_TIP_LED, 1);
    osDelay(time);
    IoTGpioSetOutputVal(HMDTU_TIP_LED, 0);
}

void Wifi_AP_led2(int time){
    IoTGpioSetOutputVal(HMDTU_TIP_LED, 0);
    osDelay(time);
    IoTGpioSetOutputVal(HMDTU_TIP_LED, 1);
    osDelay(time);
    IoTGpioSetOutputVal(HMDTU_TIP_LED, 0);
}

static bool WifiAPTask(void){
    //延时2S便于查看日志
    osDelay(200);

    //注册wifi事件的回调函数
    g_wifiEventHandler.OnHotspotStaJoin = OnHotspotStaJoinHandler;
    g_wifiEventHandler.OnHotspotStaLeave = OnHotspotStaLeaveHandler;
    g_wifiEventHandler.OnHotspotStateChanged = OnHotspotStateChangedHandler;
    error = RegisterWifiEvent(&g_wifiEventHandler);
    if (error != WIFI_SUCCESS){
        printf("[HMNetDTU]RegisterWifiEvent failed, error = %d.\r\n",error);
        return -1;
    }
    printf("[HMNetDTU]RegisterWifiEvent succeed!\r\n");
    //设置指定的热点配置
    HotspotConfig config = {0};

    strcpy(config.ssid, HMDTU_AP_SSID);
    strcpy(config.preSharedKey, HMDTU_AP_PSK);
    config.securityType = WIFI_SEC_TYPE_PSK;
    config.band = HOTSPOT_BAND_TYPE_2G;
    config.channelNum = 7;

    error = SetHotspotConfig(&config);
    if (error != WIFI_SUCCESS){
        printf("[HMNetDTU]SetHotspotConfig failed, error = %d.\r\n", error);
        return -1;
    }
    printf("[HMNetDTU]SetHotspotConfig succeed!\r\n");

    //启动wifi热点模式
    error = EnableHotspot(); 
    if (error != WIFI_SUCCESS){
        printf("[HMNetDTU]EnableHotspot failed, error = %d.\r\n", error);
        return -1;
    }
    printf("[HMNetDTU]EnableHotspot succeed!\r\n");

    //检查热点模式是否使能
    if (IsHotspotActive() == WIFI_HOTSPOT_NOT_ACTIVE){
        printf("[HMNetDTU]Wifi station is not actived.\r\n");
        return -1;
    }
    printf("[HMNetDTU]Wifi station is actived!\r\n");

    //启动dhcp
    g_lwip_netif = netifapi_netif_find("ap0");
    netifapi_dhcps_stop(g_lwip_netif);
    if (g_lwip_netif) {
        ip4_addr_t bp_gw;
        ip4_addr_t bp_ipaddr;
        ip4_addr_t bp_netmask;

        IP4_ADDR(&bp_gw, 192, 168, 1, 1);           /* input your gateway for example: 192.168.1.1 */
        IP4_ADDR(&bp_ipaddr, 192, 168, 1, 1);       /* input your IP for example: 192.168.1.1 */
        IP4_ADDR(&bp_netmask, 255, 255, 255, 0);    /* input your netmask for example: 255.255.255.0 */

        err_t ret = netifapi_netif_set_addr(g_lwip_netif, &bp_ipaddr, &bp_netmask, &bp_gw);
        if(ret != ERR_OK){
            printf("[HMNetDTU]netifapi_netif_set_addr failed, error = %d.\r\n", ret);
            return -1;
        }
        printf("netifapi_netif_set_addr succeed!\r\n");

        ret = netifapi_dhcps_start(g_lwip_netif, 0, 0);
        if(ret != ERR_OK){ 
            printf("[HMNetDTU]netifapi_dhcp_start failed, error = %d.\r\n", ret);
            return -1;
        }
        printf("[HMNetDTU]netifapi_dhcps_start succeed!\r\n");

    }

    /****************以下为UDP服务器代码***************/
	//在sock_fd 进行监听
    int sock_fd;
    //服务端地址信息
	struct sockaddr_in server_sock;

    //创建socket
	if ((sock_fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1){
		perror("socket is error.\r\n");
		return -1;
	}

	bzero(&server_sock, sizeof(server_sock));
	server_sock.sin_family = AF_INET;
	server_sock.sin_addr.s_addr = htonl(INADDR_ANY);
	server_sock.sin_port = htons(HMDTU_AP_UDP_PORT);

	//调用bind函数绑定socket和地址
	if (bind(sock_fd, (struct sockaddr *)&server_sock, sizeof(struct sockaddr)) == -1){
		perror("[HMNetDTU]bind is error.\r\n");
		return -1;
	}

    int ret;
    //客户端地址信息
    // struct sockaddr_in client_addr;
    int size_client_addr= sizeof(struct sockaddr_in);
    while (1){
        printf("[HMNetDTU]Waiting to receive data...\r\n");
        memset(HBKDTU_udp_recvBuf, 0, sizeof(HBKDTU_udp_recvBuf));
        ret = recvfrom(sock_fd, HBKDTU_udp_recvBuf, sizeof(HBKDTU_udp_recvBuf), 0, (struct sockaddr*)&WIFIAP_client_addr,(socklen_t*)&size_client_addr);
        if(ret < 0){
            printf("[HMNetDTU]UDP server receive failed!\r\n");
            return -1;
        }
        *WIFIAP_wifiDataLength = ret;
        //WIFIAP_wifiData
        memcpy(WIFIAP_wifiData, (char *)HBKDTU_udp_recvBuf, 400);
        osEventFlagsSet(WIFIAP_flagID, WIFIAP_flags);
        Wifi_AP_led2(30);
        WIFIAP_sock_fd = sock_fd;
    }
}

static void HotspotStaJoinTask(void){
    static char macAddress[32] = {0};
    StationInfo stainfo[WIFI_MAX_STA_NUM] = {0};
    StationInfo *sta_list_node = NULL;
    unsigned int size = WIFI_MAX_STA_NUM;

    error = GetStationList(stainfo, &size);
    if (error != WIFI_SUCCESS) {
        printf("[HMNetDTU]HotspotStaJoin:get list fail, error is %d.\r\n", error);
        return;
    }
    sta_list_node = stainfo;
    for (uint32_t i = 0; i < size; i++, sta_list_node++) {
    unsigned char* mac = sta_list_node->macAddress;
    snprintf(macAddress, sizeof(macAddress), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    printf("[HMNetDTU]HotspotSta[%d]: macAddress=%s.\r\n",i, macAddress);
    }
    g_apEnableSuccess++;

    Wifi_AP_led(50);
}
static void OnHotspotStaJoinHandler(StationInfo *info){
    if (info == NULL) {
        printf("[HMNetDTU]HotspotStaJoin:info is null.\r\n");
    } else {
        printf("New Sta Join\n");
        osThreadAttr_t attr;
        attr.name = "HotspotStaJoinTask";
        attr.attr_bits = 0U;
        attr.cb_mem = NULL;
        attr.cb_size = 0U;
        attr.stack_mem = NULL;
        attr.stack_size = 2048;
        attr.priority = 24;
        if (osThreadNew((osThreadFunc_t)HotspotStaJoinTask, NULL, &attr) == NULL) {
            printf("[HMNetDTU]HotspotStaJoin:create task fail!\r\n");
        }
    }
    return;
}

static void OnHotspotStaLeaveHandler(StationInfo *info){
    if (info == NULL) {
        printf("[HMNetDTU]HotspotStaLeave:info is null.\r\n");
    } 
    else {
        static char macAddress[32] = {0};
        unsigned char* mac = info->macAddress;
        snprintf(macAddress, sizeof(macAddress), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
        printf("[HMNetDTU]HotspotStaLeave: macAddress=%s, reason=%d.\r\n", macAddress, info->disconnectedReason);
        g_apEnableSuccess--;
    }
    return;
}

static void OnHotspotStateChangedHandler(int state){
    printf("[HMNetDTU]HotspotStateChanged:state is %d.\r\n", state);
    if (state == WIFI_HOTSPOT_ACTIVE) {
        printf("[HMNetDTU]wifi hotspot active.\r\n");
    } else {
        printf("[HMNetDTU]wifi hotspot noactive.\r\n");
    }
}

static void Wifi_AP_Demo(void){
    osThreadAttr_t attr;

    attr.name = "WifiAPTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 10240;
    attr.priority = 27;

    if (osThreadNew((osThreadFunc_t)WifiAPTask, NULL, &attr) == NULL){
        printf("[HMNetDTU]Falied to create WifiAPTask!\r\n");
    }
}


void startConfigWifiAp(osEventFlagsId_t flagID,uint32_t flags,char * wifiData,int ** wifiDataLength){
    WIFIAP_flagID = flagID;
    WIFIAP_flags = flags;
    WIFIAP_wifiData = wifiData;
    WIFIAP_wifiDataLength = wifiDataLength;
    Wifi_AP_led(80);
    Wifi_AP_Demo();
}

void WIFI_send_data(char * sendData,int length){
    printf("[HMNetDTU]receive bytes of data from ipaddr = %s, port = %d.\r\n", inet_ntoa(WIFIAP_client_addr.sin_addr), ntohs(WIFIAP_client_addr.sin_port));
    int ret = sendto(WIFIAP_sock_fd, sendData, length, 0, (struct sockaddr *)&WIFIAP_client_addr, sizeof(WIFIAP_client_addr));

    if (ret < 0){
        printf("[HMNetDTU]UDP server send failed!\r\n");
    }
}